package com.rogers.rmcdouga.skirmishgadget.client;

import java.util.HashMap;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.gen2.logging.shared.Log;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class AddTokenDialog extends DialogBox implements ImageURLBox.URLBox_ValidityCallback
{

	private static final String ADD_TOKEN = "Add Token";

	private static addTokenDialogUiBinder uiBinder = GWT.create(addTokenDialogUiBinder.class);

	interface addTokenDialogUiBinder extends UiBinder<Widget, AddTokenDialog> {	}
	
	interface DialogResult {
		void action(AddTokenDialog dlg);
	}
	
	// State variables
	private boolean customTokenSize_state = false;	// Has the user chosen to make the token size custom?
	private boolean validTokenName_state = true;				// Has the user selected a valid name

	// member variables
	private DialogResult okAction;
	private DialogResult cancelAction;
	private HashMap<String, Token> existingTokens;

	@UiField
	ImageURLBox tokenURLBox;
	
	@UiField
	TextBox tokenName;

	@UiField
	Button okButton;

	@UiField
	Button cancelButton;

	@UiField
	RadioButton tokenSize_5x5;

	@UiField
	RadioButton tokenSize_10x10;
	
	@UiField
	RadioButton tokenSize_CustomSize;

	@UiField
	TextBox tokenWidth;

	@UiField
	TextBox tokenHeight;

	private void init()
	{
		setText(ADD_TOKEN);
		setWidget(uiBinder.createAndBindUi(this));
		tokenURLBox.setCallback(this);
	}

	@Override
	public void show()
	{
		tokenURLBox.setUrl("");	// clear any previous URL that was in the URLBox
		setTokenName("");		// clear any previous name that was in the name TextBox
		super.show();
	}

	public AddTokenDialog() {
		super();
		init();
	}

	public AddTokenDialog(boolean autoHide, boolean modal) {
		super(autoHide, modal);
		init();
	}

	public AddTokenDialog(boolean autoHide) {
		super(autoHide);
		init();
	}

	@Override
	protected void onPreviewNativeEvent(NativePreviewEvent preview) {
		super.onPreviewNativeEvent(preview);

		NativeEvent evt = preview.getNativeEvent();
		if (evt.getType().equals("keydown")) {
			// Use the popup's key preview hooks to close the dialog when either
			// enter or escape is pressed.
			switch (evt.getKeyCode()) {
			case KeyCodes.KEY_ENTER:
				if (getOkAction() != null)
					getOkAction().action(this);
	        	hide();
	        	break;
			case KeyCodes.KEY_ESCAPE:
				if (getCancelAction() != null)
					getCancelAction().action(this);
				hide();
				break;
			}
		}
	}

	@UiHandler("okButton")
	void okButtonClick(ClickEvent e)
	{
		if (getOkAction() != null)
			getOkAction().action(this);
		hide();
	}
	
	@UiHandler("cancelButton")
	void cancelButtonClick(ClickEvent e)
	{
    	if (getCancelAction() != null)
			getCancelAction().action(this);
    	hide();
	}

	@UiHandler("tokenSize_5x5")
	void MapSize_TokenSize_5x5_Click(ClickEvent e)
	{
		setCustomTokenSize_state(false);
	}

	@UiHandler("tokenSize_10x10")
	void MapSize_TokenSize_10x10_Click(ClickEvent e)
	{
		setCustomTokenSize_state(false);
	}

	@UiHandler("tokenSize_CustomSize")
	void MapSize_tokenSize_CustomSize_Click(ClickEvent e)
	{
		setCustomTokenSize_state(true);
	}

	@UiHandler("tokenName")
	void tokenName_KeyPress(KeyPressEvent e)
	{
		DeferredCommand.addCommand(new Command(){
			public void execute() {
				checkTokenNameValidity();
			}
		});
	}
	

	@UiHandler("tokenName")
	void tokenName_KeyDown(KeyDownEvent e)
	{
		int nativeKeyCode = e.getNativeKeyCode();
		if (nativeKeyCode == KeyCodes.KEY_BACKSPACE || nativeKeyCode == KeyCodes.KEY_DELETE)
			DeferredCommand.addCommand(new Command(){
				public void execute() {
					checkTokenNameValidity();
				}
			});
	}
	

	private boolean isCustomTokenSize_state()
	{
		return customTokenSize_state;
	}

	private void setCustomTokenSize_state(boolean customTokenSizeState)
	{
		customTokenSize_state = customTokenSizeState;
		enableAndDisableFields();
	}

	@Override
	public void invalidURL()
	{
		enableAndDisableFields();
	}

	@Override
	public void validURL()
	{
		setTokenNameFromUrl(tokenURLBox.getUrl());
		enableAndDisableFields();
	}
	
	private void enableAndDisableFields()
	{
		if (!tokenURLBox.isValidURL())
		{
			okButton.setEnabled(false);
			tokenSize_5x5.setEnabled(false);
			tokenSize_10x10.setEnabled(false);
			tokenSize_CustomSize.setEnabled(false);
			tokenWidth.setEnabled(false);
			tokenHeight.setEnabled(false);
			tokenName.setEnabled(false);
		}
		else
		{
			if (validTokenName_state) {
				okButton.setEnabled(true);
			}
			else {
				okButton.setEnabled(false);
			}
			tokenSize_5x5.setEnabled(true);
			tokenSize_10x10.setEnabled(true);
			tokenSize_CustomSize.setEnabled(true);
			tokenName.setEnabled(true);
			if (isCustomTokenSize_state())
			{
				tokenWidth.setEnabled(true);
				tokenHeight.setEnabled(true);
			}
			else
			{
				tokenWidth.setEnabled(false);
				tokenHeight.setEnabled(false);
			}
		}
	}

	public DialogResult getOkAction()
	{
		return okAction;
	}

	public void setOkAction(DialogResult okAction)
	{
		this.okAction = okAction;
	}

	public DialogResult getCancelAction()
	{
		return cancelAction;
	}

	public void setCancelAction(DialogResult cancelAction)
	{
		this.cancelAction = cancelAction;
	}
	
	public String getTokenURL()
	{
		return tokenURLBox.getUrl();
	}

	public String getTokenName()
	{
		return tokenName.getText();
	}

	private void setTokenName(String tokenName)
	{
		this.tokenName.setText(tokenName);
	}

	
	private HashMap<String, Token> getExistingTokens()
	{
		return existingTokens;
	}

	public void setExistingTokens(HashMap<String, Token> existingTokens)
	{
		this.existingTokens = existingTokens;
	}

	private void setTokenNameFromUrl(String tokenUrl)
	{
		String name = tokenUrl.substring(tokenUrl.lastIndexOf('/') + 1, tokenUrl.lastIndexOf('.'));
		if (getExistingTokens() != null) {
			// Check to make sure the name is unique
			String newName = name;
			for (int count = 2; getExistingTokens().containsKey(newName); count ++) { 
				newName = name + " " + Integer.toString(count);
			}
			name = newName;
		}
		this.setTokenName(name);
	}
	
	private void checkTokenNameValidity() {
		validTokenName_state = !getExistingTokens().containsKey(getTokenName());
		Log.info("CheckTokenNameValidity=" + validTokenName_state);
		enableAndDisableFields();
	}
}
